#include "clientStdafx.h"
#include "BaseEditor.h"

#include "SceneManagerEditor.h"

using namespace Apo;

static CSceneManagerEditorFactory SceneManagerEditorFactory;

//-------------------------------------------------------------------------------
CSceneManagerEditor::CSceneManagerEditor(String typestring, EDITORTYPE etype) :CBaseEditor(typestring, etype)
{
    m_Handle = 0;
    m_SkyBoxActive = false;
    m_SkyBoxMaterial = "";
    m_SkyBoxDistance=5000.0f;
    m_UsesGizmos = false;
    m_UsesHelper = false;
    m_ConfigFile = "";
    m_EditFlags =  CAN_DROP | CAN_UNDO;
    RegisterForPostSceneUpdates();
}
//-------------------------------------------------------------------------------
CBaseEditorFactory *CSceneManagerEditor::GetFactory()
{
    return &SceneManagerEditorFactory;
}
//-------------------------------------------------------------------------------
CBaseEditorFactory *CSceneManagerEditor::GetFactoryDynamic()
{
    return &SceneManagerEditorFactory;
}
//-------------------------------------------------------------------------------
bool CSceneManagerEditor::PostSceneUpdate(SceneManager *SceneMngr, Camera *Camera, RenderWindow *RenderWindow)
{
    if(m_ConfigFile != "")
    {
	    m_Handle->setWorldGeometry(m_ConfigFile);
    }

    return false;
}
//-------------------------------------------------------------------------------
bool CSceneManagerEditor::GetObjectContextMenu(StringVector &menuitems) 
{
    menuitems.clear();
    return false;
}
//-------------------------------------------------------------------------------
void CSceneManagerEditor::OnObjectContextMenu(int menuresult) 
{
    if(menuresult == 0)
    {
    }
}
//-------------------------------------------------------------------------------
void CSceneManagerEditor::SetHandle(void *objHandle,bool display)
{
    if(m_Handle)
	    UnRegisterObjectName();
    m_Handle = (SceneManager *)objHandle;
    m_Name = m_Handle->getName();
    RegisterObjectName();
    if(display) 
        SetupPropertiesWnd();
}
 Node     *CSceneManagerEditor::GetNode() 
{
	return m_Handle->getRootSceneNode();
};
//-------------------------------------------------------------------------------
void CSceneManagerEditor::SetName(int BIND_ID,String val,bool refresh)
{
    if(val == m_Name) return;
    int i;
    while((i = val.find(" ")) != -1)
        val.erase(i,1);

    if(val.empty())
    {
	    m_System->SetProperty(this,BIND_ID,m_Name);
        return;
    }

    if(m_System->DisplayMessageDialog("Renaming a Scene Manager requires Save and Reload of the Scene.\nDo you want to continue?",DLGTYPE_YESNO) == DLGRET_YES)
    {
	    m_Name = val;
	    OgitorsRoot::getSingletonPtr()->SaveScene();
	    String filename = OgitorsRoot::getSingletonPtr()->GetProjectOptions()->ProjectDir + OgitorsRoot::getSingletonPtr()->GetProjectOptions()->ProjectName + ".ogscene";
	    OgitorsRoot::getSingletonPtr()->TerminateScene();
	    OgitorsRoot::getSingletonPtr()->LoadScene(filename);
    }
    else
	    m_System->SetProperty(this,BIND_ID,m_Name);
}
//-------------------------------------------------------------------------------
void CSceneManagerEditor::SetConfigFile(int BIND_ID,String val,bool refresh)
{
    m_ConfigFile = val;
    if(refresh) 
        m_System->SetProperty(this,BIND_ID,m_ConfigFile);
}

//-------------------------------------------------------------------------------
bool CSceneManagerEditor::SetupPropertiesWnd()
{
    if(!m_System->ClearPropertiesView(m_ObjectTypeID)) return false;

    m_System->SetProperty(this,BIND_TYPE,GetObjectTypeString());
    m_System->SetProperty(this,BIND_NAME,m_Name);
    m_System->SetProperty(this,BIND_CONFIGFILE,m_ConfigFile);

    Vector3 vDiffuse = GetAmbient();
    unsigned long cr = INTFROMRGB(vDiffuse.x * 255.0f,vDiffuse.y * 255.0f,vDiffuse.z * 255.0f);
    m_System->SetColourProperty(this,BIND_AMBIENT,cr);

    StringVector MaterialNames;
    MaterialManager::ResourceMapIterator it = MaterialManager::getSingleton().getResourceIterator();
    while(it.hasMoreElements())
    {
        ResourcePtr mRes = it.getNext();
        if(mRes->getGroup() == "ProjectResources")
        {
	        String matname = 	mRes->getName();
	        StringUtil::toLowerCase(matname);
	        if(matname.find("sky") != -1 && matname.find("skyboxplane") == -1)
	        MaterialNames.push_back(mRes->getName());
	    }
    }
    std::sort(MaterialNames.begin(),MaterialNames.end());

    m_System->FillPropertyOptions(this,BIND_SKYBOXMATERIAL,MaterialNames);

    m_System->SetProperty(this,BIND_SKYBOXMATERIAL,m_SkyBoxMaterial);
    m_System->SetProperty(this,BIND_SKYBOXACTIVE,GetSkyBoxActive());
    m_System->SetProperty(this,BIND_SKYBOXDISTANCE,m_SkyBoxDistance);

    ColourValue cFog = m_Handle->getFogColour();
    cr = INTFROMRGB(cFog.r * 255.0f,cFog.g * 255.0f,cFog.b * 255.0f);
  
    FogMode fMode = m_Handle->getFogMode();
    String fogmode;
  
    if(fMode == FOG_LINEAR)
        fogmode = "Linear";
    else if(fMode == FOG_EXP)
        fogmode = "Exp";
    else if(fMode == FOG_EXP2)
        fogmode = "Exp2";
    else
        fogmode = "None";

    m_System->SetProperty(this,CUSTOM_BINDING_START + 1, fogmode);
    m_System->SetColourProperty(this,CUSTOM_BINDING_START + 2, cr);
    m_System->SetProperty(this,CUSTOM_BINDING_START + 3, (float)m_Handle->getFogStart());
    m_System->SetProperty(this,CUSTOM_BINDING_START + 4, (float)m_Handle->getFogEnd());
    m_System->SetProperty(this,CUSTOM_BINDING_START + 5, (float)m_Handle->getFogDensity());

    return true;
}
//-------------------------------------------------------------------------------
void CSceneManagerEditor::SetAmbient(int BIND_ID,Vector3 val,bool refresh)
{
    unsigned long cr = INTFROMRGB(val.x * 255.0f,val.y * 255.0f, val.z * 255.0f);

    m_Handle->setAmbientLight(ColourValue(val.x,val.y,val.z));
    if(refresh)
    {
        m_System->SetColourProperty(this,BIND_ID,cr);
    }
    SetModified(true);
}
//-------------------------------------------------------------------------------
void CSceneManagerEditor::SetSkyBoxActive(int BIND_ID,String val,bool refresh)
{
    bool iVal = StringConverter::parseBool(val);

    if(iVal && !(m_SkyBoxMaterial.empty()) && m_SkyBoxDistance > 0.0f)
    {
        m_Handle->setSkyBox(true,m_SkyBoxMaterial,m_SkyBoxDistance);
        m_SkyBoxActive = true;
        m_System->SetProperty(this, BIND_ID,true);
    }
    else
    {
        m_Handle->setSkyBox(false,"");
        m_System->SetProperty(this, BIND_ID,false);
        m_SkyBoxActive = false;
    }
    SetModified(true);
}
//-------------------------------------------------------------------------------
void CSceneManagerEditor::SetSkyBoxMaterial(int BIND_ID,String val,bool refresh)
{
    m_SkyBoxMaterial = val;
    m_SkyBoxActive = false;

    if(m_Handle->getSkyBoxNode() != NULL)
    {
        m_Handle->setSkyBox(false,"");
        if(!(m_SkyBoxMaterial.empty()))
        {
            m_Handle->setSkyBox(true,m_SkyBoxMaterial,m_SkyBoxDistance);
            m_SkyBoxActive = true;
        }
    }
    if(refresh)
    {
        m_System->SetProperty(this,BIND_ID,val);
    }
    SetModified(true);
}
//-------------------------------------------------------------------------------
void CSceneManagerEditor::SetSkyBoxDistance(int BIND_ID,String val,bool refresh)
{
    m_SkyBoxDistance = StringConverter::parseReal(val);
    m_SkyBoxActive = false;

    if(m_Handle->getSkyBoxNode() != NULL)
    {
        m_Handle->setSkyBox(false,"");
        if(m_SkyBoxDistance > 0.0f)
        {
            m_Handle->setSkyBox(true,m_SkyBoxMaterial,m_SkyBoxDistance);
            m_SkyBoxActive = true;
        }
    }
    if(refresh)
    {
        m_System->SetProperty(this,BIND_ID,m_SkyBoxDistance);
    }
    SetModified(true);
}
//-------------------------------------------------------------------------------
void CSceneManagerEditor::GetObjectProperties(NameValuePairList &retList)
{
    retList.clear();
    retList["name"] = m_Name;
    retList["scenemanagertype"] = m_Handle->getTypeName();
    retList["configfile"] = m_ConfigFile;
    retList["ambient"] = StringConverter::toString(m_Handle->getAmbientLight());
    retList["skyboxactive"] = StringConverter::toString(GetSkyBoxActive());
    retList["skyboxmaterial"] = m_SkyBoxMaterial;
    retList["skyboxdistance"] = StringConverter::toString(m_SkyBoxDistance);

    FogMode fogMode = m_Handle->getFogMode();
    switch(fogMode)
    {
    case FOG_NONE:retList["fogmode"] = "None";break;
    case FOG_LINEAR:retList["fogmode"] = "Linear";break;
    case FOG_EXP:retList["fogmode"] = "Exp";break;
    case FOG_EXP2:retList["fogmode"] = "Exp2";break;
    }

    retList["fogcolour"] = StringConverter::toString(m_Handle->getFogColour());
    retList["fogstart"] = StringConverter::toString(m_Handle->getFogStart());
    retList["fogend"] = StringConverter::toString(m_Handle->getFogEnd());
    retList["fogdensity"] = StringConverter::toString(m_Handle->getFogDensity());
}

bool CSceneManagerEditor::HandleCustomFunction(int BIND_ID, String val)
{
    FogMode fogMode = m_Handle->getFogMode();
    ColourValue fogColour = m_Handle->getFogColour();
    Real fogStart = m_Handle->getFogStart();
    Real fogEnd = m_Handle->getFogEnd();
    Real fogDensity = m_Handle->getFogDensity();

    switch(BIND_ID)
    {
    case 1:{
               if(val == "None")
                   m_Handle->setFog(FOG_NONE);
               else if(val == "Linear")
                   m_Handle->setFog(FOG_LINEAR,fogColour,fogDensity,fogStart,fogEnd);
               else if(val == "Exp")
                   m_Handle->setFog(FOG_EXP,fogColour,fogDensity,fogStart,fogEnd);
               else if(val == "Exp2")
                   m_Handle->setFog(FOG_EXP2,fogColour,fogDensity,fogStart,fogEnd);
               break;
        }
    case 2:{
               ColourValue cDiff;
               unsigned long cr = StringConverter::parseInt(val);
               cDiff.r = (float)GetRED(cr) / 255.0f;
               cDiff.g = (float)GetGREEN(cr) / 255.0f;
               cDiff.b = (float)GetBLUE(cr) / 255.0f;
               m_Handle->setFog(fogMode,cDiff,fogDensity,fogStart,fogEnd);
               break;
           }
    case 3:    m_Handle->setFog(fogMode,fogColour,fogDensity,StringConverter::parseReal(val),fogEnd);
               break;
    case 4:    m_Handle->setFog(fogMode,fogColour,fogDensity,fogStart,StringConverter::parseReal(val));
               break;
    case 5:    m_Handle->setFog(fogMode,fogColour,StringConverter::parseReal(val),fogStart,fogEnd);
               break;
    }
    return true;
}
//-------------------------------------------------------------------------------
CBaseEditor *CSceneManagerEditor::Restore(NameValuePairList &retList)
{
    NameValuePairList theList;
    GetObjectProperties(theList);
    NameValuePairList::const_iterator ni;

    CSceneManagerEditor *object = static_cast<CSceneManagerEditor*>(CBaseEditor::Restore(retList));

    SceneManager *pSceneManager = object->m_Handle;

    if ((ni = retList.find("configfile")) != retList.end() && retList["configfile"] != object->m_ConfigFile)
    {
        object->SetConfigFile(BIND_CONFIGFILE, ni->second,false);
    }

    if ((ni = retList.find("ambient")) != retList.end())
    {
        pSceneManager->setAmbientLight(StringConverter::parseColourValue(ni->second));
    }

    if ((ni = retList.find("skyboxdistance")) != retList.end())
    {
        object->SetSkyBoxDistance(BIND_SKYBOXDISTANCE,ni->second,false);
    }

    if ((ni = retList.find("skyboxmaterial")) != retList.end())
    {
        object->SetSkyBoxMaterial(BIND_SKYBOXMATERIAL,ni->second,false);
    }

    if ((ni = retList.find("skyboxactive")) != retList.end())
    {
        object->SetSkyBoxActive(BIND_SKYBOXACTIVE,ni->second,false);
    }

    FogMode fogMode = pSceneManager->getFogMode();
    ColourValue fogColour = pSceneManager->getFogColour();
    Real fogStart = pSceneManager->getFogStart();
    Real fogEnd = pSceneManager->getFogEnd();
    Real fogDensity = pSceneManager->getFogDensity();

    if ((ni = retList.find("fogmode")) != retList.end())
    {
        String val = ni->second;
        StringUtil::toLowerCase(val);

        if(val == "none")
            fogMode = FOG_NONE;
        else if(val == "linear")
            fogMode = FOG_LINEAR;
        else if(val == "exp")
            fogMode = FOG_EXP;
        else if(val == "exp2")
            fogMode = FOG_EXP2;
    }

    if ((ni = retList.find("fogcolour")) != retList.end())
    {
        fogColour = StringConverter::parseColourValue(ni->second);
    }

    if ((ni = retList.find("fogstart")) != retList.end())
    {
        fogStart = StringConverter::parseReal(ni->second);
    }

    if ((ni = retList.find("fogend")) != retList.end())
    {
        fogEnd = StringConverter::parseReal(ni->second);
    }

    if ((ni = retList.find("fogdensity")) != retList.end())
    {
        fogDensity = StringConverter::parseReal(ni->second);
    }

    pSceneManager->setFog(fogMode,fogColour,fogDensity,fogStart,fogEnd);

    retList = theList;
    return object;
}
//-----------------------------------------------------------------------------------------

//-------------------------------------------------------------------------------
//--------CSCENEMANAGEREDITORFACTORY---------------------------------------------
//-------------------------------------------------------------------------------
CBaseEditor *CSceneManagerEditorFactory::CreateObject(CBaseEditor **parent, NameValuePairList &params)
{
    SceneManager* pSceneManager;
    String tail;
    String objName = params["name"];

    CSceneManagerEditor *object = new CSceneManagerEditor();

    NameValuePairList::const_iterator ni;

    pSceneManager = Root::getSingletonPtr()->createSceneManager("OctreeSceneManager",objName);

    object->SetHandle(pSceneManager,false);

    if ((ni = params.find("ambient")) != params.end())
    {
        pSceneManager->setAmbientLight(StringConverter::parseColourValue(ni->second));
    }

    if ((ni = params.find("configfile")) != params.end())
    {
        object->SetConfigFile(BIND_CONFIGFILE, ni->second,false);
    }

    if ((ni = params.find("skyboxdistance")) != params.end())
    {
        object->SetSkyBoxDistance(BIND_SKYBOXDISTANCE,ni->second,false);
    }

    if ((ni = params.find("skyboxmaterial")) != params.end())
    {
        object->SetSkyBoxMaterial(BIND_SKYBOXMATERIAL,ni->second,false);
    }

    if ((ni = params.find("skyboxactive")) != params.end())
    {
        object->SetSkyBoxActive(BIND_SKYBOXACTIVE,ni->second,false);
    }

    FogMode fogMode = pSceneManager->getFogMode();
    ColourValue fogColour = pSceneManager->getFogColour();
    Real fogStart = pSceneManager->getFogStart();
    Real fogEnd = pSceneManager->getFogEnd();
    Real fogDensity = pSceneManager->getFogDensity();

    if ((ni = params.find("fogmode")) != params.end())
    {
        String val = ni->second;
        StringUtil::toLowerCase(val);

        if(val == "none")
            fogMode = FOG_NONE;
        else if(val == "linear")
            fogMode = FOG_LINEAR;
        else if(val == "exp")
            fogMode = FOG_EXP;
        else if(val == "exp2")
            fogMode = FOG_EXP2;
    }

    if ((ni = params.find("fogcolour")) != params.end())
    {
        fogColour = StringConverter::parseColourValue(ni->second);
    }

    if ((ni = params.find("fogstart")) != params.end())
    {
        fogStart = StringConverter::parseReal(ni->second);
    }

    if ((ni = params.find("fogend")) != params.end())
    {
        fogEnd = StringConverter::parseReal(ni->second);
    }

    if ((ni = params.find("fogdensity")) != params.end())
    {
        fogDensity = StringConverter::parseReal(ni->second);
    }

    pSceneManager->setFog(fogMode,fogColour,fogDensity,fogStart,fogEnd);

    m_InstanceCount++;
    return object;
}
//-------------------------------------------------------------------------------
